package com.simple.gulimall.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.simple.gulimall.product.service.CategoryBrandRelationService;
import com.simple.gulimall.product.vo.Catalog2Vo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.lang.reflect.Array;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.simple.common.utils.PageUtils;
import com.simple.common.utils.Query;

import com.simple.gulimall.product.dao.CategoryDao;
import com.simple.gulimall.product.entity.CategoryEntity;
import com.simple.gulimall.product.service.CategoryService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Resource
    CategoryBrandRelationService categoryBrandRelationService;
    @Autowired
    StringRedisTemplate redisTemplate;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<CategoryEntity> listWithTree() {
        //查询出所有的分类信息
        List<CategoryEntity> entities = baseMapper.selectList(null);

        List<CategoryEntity> levelOneMenus = new ArrayList<>();
        List<CategoryEntity> levelTwoMenus = new ArrayList<>();
        List<CategoryEntity> levelThreeMenus = new ArrayList<>();
        //找到所有的一级分类
        for (CategoryEntity entity : entities) {
            if (entity.getParentCid()==0){

                List<CategoryEntity> children = getChildren(entity, entities);
                if (children!=null){
                    entity.setChildren(children);
                }
                levelOneMenus.add(entity);
            }
        }
        //对分类中的元素按sort属性正序排列
        levelOneMenus.sort(Comparator.comparingInt(o -> (o.getSort() == null ? 0 : o.getSort())));

        return levelOneMenus;
    }

    @Override
    public void removeMenuByIds(List<Long> catIds) {
        //TODO 判断是否还有其他的引用
        baseMapper.deleteBatchIds(catIds);
    }

    @Override
    public Long[] findCatelogPath(Long catelogId) {
        List<Long> paths = new ArrayList<>();
        CategoryEntity category = this.getById(catelogId);

        findParentPath(catelogId,paths);
        return paths.toArray(new Long[0]);
    }

    /**
     * 级联更新所有有关的数据
     * @param category
     */
    @Transactional
    @Override
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        if (!StringUtils.isEmpty(category.getName())){
            categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
        }
        //TODO 更新其他关联
    }

    @Override
    public List<CategoryEntity> getLevelOneCategories() {
        List<CategoryEntity> entities = this.list(new QueryWrapper<CategoryEntity>().eq("cat_id",1L));

        return entities;
    }

    /**
     * 采用redis作为缓存
     * 压力测试  虚拟机最大内存100m，50并发下，4min后吞吐量606/s,90% 89ms, 95% 92ms 99% 98ms
     * @return
     */
    @Override
    public Map<String, List<Catalog2Vo>> getCatalogJson(){
        // 从Redis中获取catalogJson
        String json = redisTemplate.opsForValue().get("catalogJson");
        // 如果缓存中没有，则从数据库中查找
        if (StringUtils.isEmpty(json)){
            Map<String, List<Catalog2Vo>> catalogJson = getCatalogJsonFromDb();
            // 将查找到的结果序列化为Json字符串再存入到redis中
            String jsonString = JSON.toJSONString(catalogJson);
            redisTemplate.opsForValue().set("catalogJson",jsonString);
            return catalogJson;
        }
        // 如果缓存中查找到了，则将Json字符串反序列化为需要的Map对象
        return JSON.parseObject(json, new TypeReference<Map<String, List<Catalog2Vo>>>() {});
    }


    /**
     * 压力测试  虚拟机最大内存100m，50并发下，4min后吞吐量238/s,90% 364ms, 95% 389ms 99% 579ms
     * @return
     */
    public Map<String, List<Catalog2Vo>> getCatalogJsonFromDb() {
        // 1、查出所有一级分类信息
        List<CategoryEntity> categoryEntities = this.list();
        List<CategoryEntity> levelOneCategories = getParent_cid(categoryEntities,0L);
        Map<String, List<Catalog2Vo>> collect = levelOneCategories.stream().collect(Collectors.toMap(key -> key.getCatId().toString(), levelOneCategory -> {
            // 根据一级分类查询二级分类的信息
            List<CategoryEntity> levelTwoCategories = getParent_cid(categoryEntities, levelOneCategory.getCatId());
            List<Catalog2Vo> catalog2Vos = null;
            if (levelTwoCategories != null) {
                // 封装二级分类数据
                catalog2Vos = levelTwoCategories.stream().map(levelTwoCategory -> {
                    Catalog2Vo catalog2Vo = new Catalog2Vo();
                    catalog2Vo.setCatalog1Id(levelOneCategory.getCatId().toString());
                    catalog2Vo.setId(levelTwoCategory.getCatId().toString());
                    catalog2Vo.setName(levelTwoCategory.getName());
                    // 根据二级分类查询三级分类信息
                    List<CategoryEntity> levelThreeCategories = getParent_cid(categoryEntities, levelTwoCategory.getCatId());
                    List<Catalog2Vo.Catalog3Vo> catalog3Vos = levelThreeCategories.stream().map(levelThreeCategory -> {
                        // 封装三级分类数据
                        Catalog2Vo.Catalog3Vo catalog3Vo = new Catalog2Vo.Catalog3Vo();
                        catalog3Vo.setId(levelThreeCategory.getCatId().toString());
                        catalog3Vo.setName(levelThreeCategory.getName());
                        catalog3Vo.setCatalog2Id(levelTwoCategory.getCatId().toString());
                        return catalog3Vo;
                    }).collect(Collectors.toList());
                    catalog2Vo.setCatalog3List(catalog3Vos);
                    return catalog2Vo;
                }).collect(Collectors.toList());
            }
            return catalog2Vos;
        }));
        return collect;
    }

    public List<CategoryEntity> getParent_cid(List<CategoryEntity> categoryEntityList, Long parentCid) {
        return categoryEntityList.stream().filter(item -> item.getParentCid() == parentCid).collect(Collectors.toList());

    }

    private List<Long> findParentPath(Long catelogId, List<Long> paths){
        CategoryEntity category = this.getById(catelogId);
        if (category.getParentCid()!=0){
            findParentPath(category.getParentCid(),paths);
        }
        paths.add(category.getCatId());
        return paths;
    }

    public List<CategoryEntity> getChildren(CategoryEntity rootCategory, List<CategoryEntity> all){
        List<CategoryEntity> children = new ArrayList<>();
        for (CategoryEntity entity : all) {
            if (rootCategory.getCatId().equals(entity.getParentCid())){
                //递归获取分类下的子分类
                List<CategoryEntity> subChildren = getChildren(entity, all);
                if (subChildren!=null)
                    entity.setChildren(subChildren);
                children.add(entity);
            }

        }
        //对分类中的元素按sort属性正序排列
        children.sort(Comparator.comparingInt(o -> (o.getSort() == null ? 0 : o.getSort())));
        return children;

    }


}